#pragma once
#include <iostream>
using namespace std;

class bounded_vector
{
private:
	int lowIndex;
	int highIndex;
	int *vptr;
	int size;

	class iterator
	{

	private:
		int *iteratorptr;

	public:
		iterator(){}
		iterator(int *ptr){ iteratorptr = ptr; }
		iterator& operator++(int junk){ iteratorptr++; return *this;}
		bool operator==(const iterator &rhs) { return iteratorptr == rhs.iteratorptr; }
		bool operator !=(const iterator &rhs) { return iteratorptr != rhs.iteratorptr; }
		int& operator*() { return *iteratorptr; }
		int* operator->() { return iteratorptr; }
	};

public:

	bounded_vector()
	{
		this->lowIndex = 0;
		this->highIndex = 0;
		this->vptr = nullptr;
		this->size = 0;
	}

	bounded_vector(int lowIndex, int highIndex)
	{
		this->lowIndex = lowIndex;
		this->highIndex = highIndex;
		this->size = highIndex - lowIndex + 1;
		this->vptr = new int[size];
		for (int i = 0; i < size; i++)
		{
			vptr[i] = 0;
		}
	}

	bounded_vector(const bounded_vector &obj)
	{
		this->lowIndex = obj.lowIndex;
		this->highIndex = obj.highIndex;
		this->size = obj.size;
		this->vptr = new int[this->size];

		for (int i = 0; i < size; i++)
		{
			this->vptr[i] = obj.vptr[i];
		}	
	}

	void clear()
	{
		if (vptr == nullptr)
		{
			return;
		}
		else
		{
			delete[] vptr;
		}
	}

	bounded_vector &operator=(const bounded_vector &obj)
	{
		this->clear();
		
		this->lowIndex = obj.lowIndex;
		this->highIndex = obj.highIndex;
		this->size = obj.size;
		this->vptr = new int[this->size];

		for (int i = 0; i < size; i++)
		{
			this->vptr[i] = obj.vptr[i];
		}

		return *this;
	}

	int &operator[](int number)
	{
		if (number >= lowIndex && number <= highIndex)
		{
			return vptr[number - lowIndex];
		}
		else
		{
			throw exception("bounded_vector::operator[], out of bounds");
		}
	}

	int total_sum()
	{
		int sum = 0;
		for (int i = 0; i < size; i++)
		{
			sum += vptr[i];
		}

		return sum;
	}

	void print()
	{
		for (int i = 0; i < size; i++)
		{
			char c = i + lowIndex;
			cout << c << ": " << vptr[i] << endl;
		}
	}

	bounded_vector &operator+(const bounded_vector &obj)
	{
		if (obj.lowIndex < this->lowIndex)
		{
			this->lowIndex = obj.lowIndex;
		}

		if (obj.highIndex > this->highIndex)
		{
			this->highIndex = obj.highIndex;
		}

		if (obj.size > this->size)
		{
			int *temp = new int[obj.size];
			for (int i = 0; i < size; i++)
			{
				temp[i] = this->vptr[i] + obj.vptr[i];
			}

			for (int i = size; i < obj.size; i++)
			{
				temp[i] = obj.vptr[i];
			}

			delete[] vptr;
			vptr = temp;
			
		}

		else
		{
			for (int i = 0; i < obj.size; i++)
			{
				vptr[i] = vptr[i] + obj.vptr[i];
			}
		}

		return *this;
	}





	bool is_empty() { return vptr == nullptr; }
	int GetSize(){ return this->size; }


	~bounded_vector()
	{
		clear();
	}


	iterator begin()
	{
		return iterator(vptr);
	}

	iterator end()
	{
		return iterator(&(vptr[size]));
	}
	

};

